<script setup lang="ts" name="SystemRoleDataPermitForm">
import { storeToRefs } from 'pinia'
import { useAppStoreWithOut } from '@/store/modules/app'
import { getIntDictOptions } from '@/utils/dict'
import { DICT_TYPE } from '@/enums/dictEnums'
import { defaultProps, handleTree, treeLevel } from '@/utils/tree'
import { SystemDataScopeEnum } from '@/enums/systemEnums'
import { RoleType } from '@/api/system/role'
import { DepartApi } from '@/api/system/depart'
import { PermitApi } from '@/api/system/permit'
const appStore = useAppStoreWithOut()
const { systemConfig } = storeToRefs(appStore)

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

const visible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formData = ref({
  id: undefined as number | undefined,
  name: '',
  code: '',
  dataScope: undefined as number | undefined,
  dataScopeDepartIds: []
})
const formRef = ref() // 表单 Ref
const departOptions = ref<any[]>([]) // 部门树形结构
const departExpand = ref(true) // 展开/折叠
const treeRef = ref() // 菜单树组件 Ref
const treeNodeAll = ref(false) // 全选/全不选
const checkStrictly = ref(true) // 是否严格模式，即父子不关联

/** 打开弹窗 */
const open = async (row: RoleType) => {
  visible.value = true
  resetForm()
  // 加载 Depart 列表。注意，必须放在前面，不然下面 setChecked 没数据节点
  departOptions.value = handleTree(await DepartApi.simple())
  treeLevel(departOptions.value, false, [], 0)
  // 设置数据
  formData.value.id = row.id
  formData.value.name = row.name
  formData.value.code = row.code
  formData.value.dataScope = row.dataScope
  await nextTick()
  // 需要在 DOM 渲染完成后，再设置选中状态
  row.dataScopeDepartIds?.forEach((departId: number): void => {
    treeRef.value.setChecked(departId, true, false)
  })
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调
const submitForm = async () => {
  formLoading.value = true
  try {
    const data = {
      roleId: formData.value.id!,
      dataScope: formData.value.dataScope!,
      dataScopeDepartIds:
        formData.value.dataScope !== SystemDataScopeEnum.DEPART_CUSTOM
          ? []
          : treeRef.value.getCheckedKeys(false)
    }
    console.log(data)
    await PermitApi.Assign.roleDataScope(data)
    message.success(t('message', 'updateSuccess'))
    visible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  // 重置选项
  treeNodeAll.value = false
  departExpand.value = true
  checkStrictly.value = true
  // 重置表单
  formData.value = {
    id: undefined,
    name: '',
    code: '',
    dataScope: undefined,
    dataScopeDepartIds: []
  }
  treeRef.value?.setCheckedNodes([])
  formRef.value?.resetFields()
}

/** 全选/全不选 */
const handleCheckedTreeNodeAll = () => {
  treeRef.value.setCheckedNodes(treeNodeAll.value ? departOptions.value : [])
}

/** 展开/折叠全部 */
const handleCheckedTreeExpand = () => {
  const nodes = treeRef.value?.store.nodesMap
  for (let node in nodes) {
    if (nodes[node].expanded === departExpand.value) {
      continue
    }
    nodes[node].expanded = departExpand.value
  }
}
</script>

<template>
  <Dialog v-model="visible" :title="t('sys.role', 'data')" :width="formData.dataScope === SystemDataScopeEnum.DEPART_CUSTOM ? '960' : '480'">
    <el-form ref="formRef" v-loading="formLoading && systemConfig.loadingType === 'module'" :model="formData" label-width="80px">
      <el-form-item :label="t('sys.role', 'name')">
        <el-tag>{{ formData.name }}</el-tag>
      </el-form-item>
      <el-form-item :label="t('sys.role', 'code')">
        <el-tag>{{ formData.code }}</el-tag>
      </el-form-item>
      <el-form-item :label="t('sys.role', 'scope')">
        <el-select v-model="formData.dataScope" clearable>
          <el-option v-for="item in getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item v-if="formData.dataScope === SystemDataScopeEnum.DEPART_CUSTOM" label=" " label-width="80px">
        <el-card class="w-full h-400px m-6px" shadow="never">
          <template #header>
            {{ t('sys.role', 'select') }}
            <el-switch v-model="treeNodeAll" class="mr-24px" :active-text="t('status', 'yes')" :inactive-text="t('status', 'no')" inline-prompt @change="handleCheckedTreeNodeAll()" />
            {{ t('sys.role', 'fold') }}
            <el-switch v-model="departExpand" class="mr-24px" :active-text="t('action', 'unfold')" :inactive-text="t('action', 'fold')" inline-prompt @change="handleCheckedTreeExpand" />
            {{ t('sys.role', 'linkage') }}
            <el-switch v-model="checkStrictly" :active-text="t('status', 'yes')" :inactive-text="t('status', 'no')" inline-prompt />
          </template>
          <el-scrollbar>
            <el-tree ref="treeRef" class="tree-level" :check-strictly="!checkStrictly" :data="departOptions" :props="defaultProps" default-expand-all :empty-text="t('common', 'loading')" node-key="id" show-checkbox>
              <template #default="{ node, data }">
                <span class="item-tree-node">
                  <span>{{ node.label }}</span>
                  <template v-for="item in data.level">
                    <span v-if="!data.hideLine.includes(item)" :key="item" :class="['item-tree-node-line-vertical', data.isLast && item == data.level ? 'is-last' : '', data.isFirst && data.level === 1 ? 'is-first' : '']" :style="{ left: 18 * (item - 1) + 12 + 'px' }" />
                  </template>
                  <span v-if="!data.isLeaf" class="item-tree-node-line-vertical is-first" :style="{ left: 18 * (data.level) + 12 + 'px' }" />
                  <span class="item-tree-node-line-horizontal" :style="{ left: 18 * (data.level - 1) + 12 + 'px' }" />
                </span>
              </template>
            </el-tree>
          </el-scrollbar>
        </el-card>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="visible = false">{{ t('action', 'cancel') }}</el-button>
      <el-button :disabled="formLoading" type="primary" @click="submitForm">{{ t('action', 'confirm') }}</el-button>
    </template>
  </Dialog>
</template>

<style scoped lang="scss">
.el-card{
  display: flex;
  flex-direction: column;

  :deep(.el-card__header){
    padding: 12px var(--el-space);
    line-height: 0;
  }

  :deep(.el-card__body) {
    position: relative;
    display: flex;
    flex: 1;

    .el-scrollbar{
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;

      .el-scrollbar__view {
        padding: var(--el-space);
      }
    }
  }
}
</style>
